var removeNthFromEnd = function (head, n) {
    // 创建一个虚拟头节点  很重要
    //以 while 循环的条件 fast.next 永远不会为真，slow 也就永远不会移动，最后尝试访问 slow.next.next 时会抛出错误（因为 slow.next 是 null）
    let dummy = new ListNode(0);
    dummy.next = head;
    let fast = dummy;
    let slow = dummy;

    // 先让fast指针前进n步  
    for (let i = 0; i <= n; i++) {
        fast = fast.next;
    }

    // 当fast到达链表末尾时，slow指向要删除的节点的前一个节点  
    while (fast !== null) {
        fast = fast.next;
        slow = slow.next;
    }

    // 删除节点  
    slow.next = slow.next.next;

    // 返回虚拟头节点的下一个节点，即修改后的链表头节点  
    return dummy.next;
};

